package com.netx.ebs;
import java.net.URLDecoder;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Cookie;
import com.netx.data.Connection;
import com.netx.data.DatabaseException;
import com.netx.generics.basic.Checker;
import com.netx.generics.basic.IntegrityException;
import com.netx.generics.util.Strings;


class EbsRequestImpl extends HttpServletRequestWrapper implements EbsRequest {

	private final ServletContext _srvCtx;
	private final EbsContext _ebsCtx;
	private Connection _connection;

	EbsRequestImpl(HttpServletRequest request, ServletContext srvCtx, EbsContext ebsCtx) {
		super(request);
		_srvCtx = srvCtx;
		_ebsCtx = ebsCtx;
		_connection = null;
	}

	public ServletContext getServletContext() {
		return _srvCtx;
	}
	
	public EbsContext getEbsContext() {
		return _ebsCtx;
	}

	public Session getUserSession() {
		Session s = (Session)getAttribute(Constants.REQUEST_SESSION);
		if(s != null) {
			s.resetLastAccessed();
		}
		return s;
	}

	public Connection getDatabaseConnection() throws DatabaseException {
		if(_connection != null) {
			_connection.close();
		}
		_connection = _ebsCtx.getDatabase().getConnection();
		return _connection;
	}
	
	// For EbsServlet:
	void closeConnection() throws DatabaseException {
		if(_connection != null) {
			_connection.close();
		}
	}
	
	public Cookie getCookie(String name) {
		Checker.checkEmpty(name, "name");
		Cookie[] cookies = getCookies();
		if(cookies == null) {
			return null;
		}
		for(int i=0; i<cookies.length; i++) {
			if(cookies[i].getName().equals(name)) {
				return cookies[i];
			}
		}
		return null;
	}
	
	public String getQueryString(boolean decode) {
		if(decode) {
			String qs = super.getQueryString();
			if(qs == null) {
				return null;
			}
			else {
				try {
					return URLDecoder.decode(qs, _ebsCtx.getCharset());
				}
				catch(UnsupportedEncodingException uee) {
					throw new IntegrityException(uee);
				}
			}
		}
		else {
			return super.getQueryString();
		}
	}

	public String getCompleteRequestURL(boolean decode) {
		String query = getQueryString(decode);
		return getRequestURL().append(query==null?"":"?"+query).toString();
	}

	public String getCompleteRequestURL() {
		return getCompleteRequestURL(false);
	}

	public String getParameter(String name) {
		Checker.checkEmpty(name, "name");
		String param = super.getParameter(name);
		return Strings.isEmpty(param) ? null : param.trim();
	}

	public String getParameter(String name, boolean required) {
		String param = getParameter(name);
		if(required && param == null) {
			throw new IllegalOperationException(_getRequiredParameterMsg(name), this);
		}
		else {
			return param;
		}
	}

	public Byte getByteParameter(String name, boolean required) {
		String param = getParameter(name, required);
		if(param == null) {
			return null;
		}
		else {
			try {
				return new Byte(param);
			}
			catch(NumberFormatException nfe) {
				throw new IllegalOperationException(_getIllegalFormatMsg(name, "byte", param), this);
			}
		}
	}

	public Byte getByteParameter(String name) {
		return getByteParameter(name, false);
	}

	public Short getShortParameter(String name, boolean required) {
		String param = getParameter(name, required);
		if(param == null) {
			return null;
		}
		else {
			try {
				return new Short(param);
			}
			catch(NumberFormatException nfe) {
				throw new IllegalOperationException(_getIllegalFormatMsg(name, "short", param), this);
			}
		}
	}

	public Short getShortParameter(String name) {
		return getShortParameter(name, false);
	}

	public Integer getIntParameter(String name, boolean required) {
		String param = getParameter(name, required);
		if(param == null) {
			return null;
		}
		else {
			try {
				return new Integer(param);
			}
			catch(NumberFormatException nfe) {
				throw new IllegalOperationException(_getIllegalFormatMsg(name, "int", param), this);
			}
		}
	}

	public Integer getIntParameter(String name) {
		return getIntParameter(name, false);
	}

	public Long getLongParameter(String name, boolean required) {
		String param = getParameter(name, required);
		if(param == null) {
			return null;
		}
		else {
			try {
				return new Long(param);
			}
			catch(NumberFormatException nfe) {
				throw new IllegalOperationException(_getIllegalFormatMsg(name, "long", param), this);
			}
		}
	}

	public Long getLongParameter(String name) {
		return getLongParameter(name, false);
	}

	public Float getFloatParameter(String name, boolean required) {
		String param = getParameter(name, required);
		if(param == null) {
			return null;
		}
		else {
			try {
				return new Float(param);
			}
			catch(NumberFormatException nfe) {
				throw new IllegalOperationException(_getIllegalFormatMsg(name, "float", param), this);
			}
		}
	}

	public Float getFloatParameter(String name) {
		return getFloatParameter(name, false);
	}

	public Double getDoubleParameter(String name, boolean required) {
		String param = getParameter(name, required);
		if(param == null) {
			return null;
		}
		else {
			try {
				return new Double(param);
			}
			catch(NumberFormatException nfe) {
				throw new IllegalOperationException(_getIllegalFormatMsg(name, "double", param), this);
			}
		}
	}

	public Double getDoubleParameter(String name) {
		return getDoubleParameter(name, false);
	}

	public boolean getBooleanParameter(String name) {
		return getParameter(name) != null;
	}

	private String _getRequiredParameterMsg(String name) {
		return "required parameter \""+name+"\" not found";
	}

	private String _getIllegalFormatMsg(String name, String type, String value) {
		return "illegal format for "+type+" parameter \""+name+"\": "+value;
	}
}
